#include <stddef.h>
#include "bsp_can_bus.h"
#include "can_config.h"
#include "stm32f4xx_hal.h"
#include "bsp.h"

/**
 * @brief CAN数据传输
 * 
 * @param p_can_msg 待发送的CAN消息体指针
 * @param number CAN编号，=0：CAN1，=1：CAN2
 * @return uint8_t 0：成功  other：失败
 */
uint8_t canTransmit(can_msg_t *p_can_msg, uint8_t number)
{
    uint32_t tx_mailbox = 0; // 获取空的发送邮箱号,HAL_CAN_AddTxMessage函数需要
    uint32_t free_tx_mailbox_num = 0;
    CAN_TxHeaderTypeDef tx_header;
    if (NULL == p_can_msg)
    {
        return 0xff;
    }

    tx_header.IDE = CAN_ID_STD;          // ID类型：标准帧
    tx_header.RTR = CAN_RTR_DATA;        // 帧类型：数据帧
    tx_header.StdId = p_can_msg->cob_id; // 标准帧ID,最大11位
    tx_header.DLC = p_can_msg->data_len;
    tx_header.TransmitGlobalTime = DISABLE;

    // TODO:1.考虑发送方式由阻塞式发送改为异步发送，利用CAN发送中断来处理
    // TODO:2.考虑增加RTOS系统回调函数，改为RTOS阻塞，避免阻塞低优先级任务，经测试此处发送阻塞可以达到0.3ms，如果总线出现异常阻塞时间会更高
    // 等待有空闲邮箱可用
    do
    { 
        free_tx_mailbox_num = HAL_CAN_GetTxMailboxesFreeLevel(number == 0 ? &hcanx[CAN1_INDEX] : &hcanx[CAN2_INDEX]);
    }while (0 == free_tx_mailbox_num);

    if (HAL_CAN_AddTxMessage(number == 0 ? &hcanx[CAN1_INDEX] : &hcanx[CAN2_INDEX], &tx_header, p_can_msg->data, &tx_mailbox) != HAL_OK)
    {
        // transmit request error
        Error_Handler(__FILE__, __LINE__);
    }
    return 0;
}

// CAN帧处理回调函数，由外部调用实现
pfunc_canRxDataProcess cmdCanRxDataProcessCallback = NULL;
pfunc_canRxDataProcess motorCanRxDataProcessCallback = NULL;  
/**
 * @brief Fifo0接收中断回调
 * 
 * @param hcan CAN句柄
 */ 
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    CAN_RxHeaderTypeDef can_rx_hdr;
    // static can_msg_t can1_msg;
    static CanMessage can1_msg;
    if (CMD_CAN == hcan->Instance)
    {
        // 接收数据
        if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can_rx_hdr, can1_msg.m_data) == HAL_OK) // 获得接收到的数据头和数据
        {
                
            can1_msg.m_extend = can_rx_hdr.IDE;         /* 扩展帧标识符 */
            if(can1_msg.m_extend == CAN_ID_STD)
                can1_msg.m_canID = can_rx_hdr.StdId;    /* 标准帧ID */
            else
                can1_msg.m_canID = can_rx_hdr.ExtId;    /* 扩展帧ID */

            can1_msg.m_dataLen = can_rx_hdr.DLC;    
            if (cmdCanRxDataProcessCallback)
            {
                /* CAN1回调 */
                cmdCanRxDataProcessCallback(&can1_msg);
            }        
            // HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING); // 再次使能FIFO0接收中断
        }
    }
}

/**
 * @brief Fifo1接收中断回调
 * 
 * @param hcan CAN句柄
 */
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    // TODO:修改函数，接收数据存放到CAN接收缓存中
    CAN_RxHeaderTypeDef can_rx_hdr;
    static can_msg_t can2_msg;
    if (MC_CAN == hcan->Instance)
    {
        // 接收数据
        if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO1, &can_rx_hdr, can2_msg.data) == HAL_OK) // 获得接收到的数据头和数据
        {
            can2_msg.cob_id = can_rx_hdr.StdId;
            can2_msg.data_len = can_rx_hdr.DLC;
            if (motorCanRxDataProcessCallback)
            {            
                motorCanRxDataProcessCallback(&can2_msg);
            }
            // HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO1_MSG_PENDING); // 再次使能FIFO1接收中断
        }
    }
}

// HAL_CAN_xxxCallback
/**
  * @brief This function handles CAN1 RX0 interrupts.
  */
void CAN1_RX0_IRQHandler(void)
{
    HAL_CAN_IRQHandler(&hcanx[CAN1_INDEX]);
}

/**
  * @brief This function handles CAN1 RX1 interrupts.
  */
void CAN1_RX1_IRQHandler(void)
{
    HAL_CAN_IRQHandler(&hcanx[CAN1_INDEX]);
}  
/**
  * @brief This function handles CAN2 RX1 interrupts.
  */
void CAN2_RX1_IRQHandler(void)
{
    HAL_CAN_IRQHandler(&hcanx[CAN2_INDEX]);
}


/**
  * @brief This function handles CAN2 RX0 interrupts.
  */
void CAN2_RX0_IRQHandler(void)
{
    HAL_CAN_IRQHandler(&hcanx[CAN2_INDEX]);
}


